package com.ligq.h265toupinpush.avmetting

import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.util.Log
import com.ligq.common.constants.FrameType
import com.ligq.common.utils.YuvUtils

class MeetingH264Encoder constructor() {
    private lateinit var mMediaCodec: MediaCodec
    private var mSocketLive: SocketLive? = null
    private var width = 0
    private var height = 0
    private lateinit var spsData: ByteArray

    constructor(socketLive: SocketLive) : this() {
        this.mSocketLive = socketLive
    }

    //用于计算PTS
    private var index = 0
    fun initEncoder(width: Int, height: Int) {
        this.width = width
        this.height = height
        try {
            val mediaFormat =
                MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, height, width)
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10)
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height)
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30)
            mediaFormat.setInteger(
                MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible
            )
            mMediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)
            mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            mMediaCodec.start()
        } catch (e: Exception) {
            Log.e(TAG, "initEncoder: ", e)
        }
    }

    fun encode(data: ByteArray) {
        val nv12 = YuvUtils.portraitDataRawFront2(YuvUtils.nv21ToNv12(data), width, height)
        try {
            val inputIndex = mMediaCodec.dequeueInputBuffer(10000)
            if (inputIndex >= 0) {
                val inputBuffer = mMediaCodec.getInputBuffer(inputIndex)
                inputBuffer?.clear()
                inputBuffer?.put(nv12)
                mMediaCodec.queueInputBuffer(
                    inputIndex,
                    0,
                    nv12.size,
                    (1000000 * index / 30).toLong(),
                    0
                )
                index++
            }

            val bufferInfo = MediaCodec.BufferInfo()
            val outIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
            if (outIndex >= 0) {
                val outputBuffer = mMediaCodec.getOutputBuffer(outIndex)
                val encodeData = ByteArray(outputBuffer!!.remaining())
                outputBuffer.get(encodeData)
                mMediaCodec.releaseOutputBuffer(outIndex, false)
                dealFrame(encodeData)
            }
        } catch (e: Exception) {
            Log.e(TAG, "encode: ", e)
        }
    }

    private fun dealFrame(bytes: ByteArray) {
        var offset = 4
        if (bytes[2].toInt() == 0x01) {
            offset = 3
        }
        val sendData = when (bytes[offset].toInt() and 0x1f) {
            FrameType.TYPE_H264_SPS.frameType -> {
                spsData = bytes
                bytes
            }
            FrameType.TYPE_H264_I.frameType -> {
                val temp = ByteArray(bytes.size + spsData.size)
                System.arraycopy(spsData, 0, temp, 0, spsData.size)
                System.arraycopy(bytes, 0, temp, spsData.size, bytes.size)
                temp
            }
            else -> {
                bytes
            }
        }
        mSocketLive?.sendData(sendData)
    }

}